package com.yx.backstage.reptile;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yx.backstage.enums.IntBoolean;
import com.yx.backstage.enums.NoticeType;
import com.yx.backstage.model.*;
import com.yx.backstage.service.*;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.Objects;

/**
 * @author YangXiong
 */
@Component
@Slf4j
@Data
public class GetBookMessage implements Runnable, ApplicationContextAware {
    private static final int TIME_OUT = 10000;
    @Resource
    private BookMessageService bookMessageService;
    @Resource
    private ChapterMessageService chapterMessageService;
    @Resource
    private SystemNoticeService systemNoticeService;
    @Resource
    private NoticeUserService noticeUserService;
    @Resource
    private SysUserService sysUserService;

    private ApplicationContext context;

    @Scheduled(cron = "0 50 15 * * ? ")
    public void getBookMessage() {
        run();
    }

    @Override
    public void run() {
        boolean isRun = true;
        while (isRun) {
            try {
                int flag = 0;
                int i = 1;
                String baseUrl = "http://www.siluwx.org";
                Document index = getDocument(baseUrl);
                Element body = index.body();
                Elements item = body.getElementsByClass("item");
                log.info("========解析开始=================请等待！！！！");
                for (Element element : item) {
                    BookMessage bookMessage = new BookMessage();
                    String name = element.select("a").text();
                    if (name.startsWith("诸天皇帝") || name.startsWith("对不起")) {
                        //这两本书有问题，舍弃不要
                        continue;
                    }
                    bookMessage.setName(name);
                    log.info("==>开始抓取第{}本书{}==", flag + i, name);
                    String img = element.select("img").attr("src");
                    bookMessage.setUrl(baseUrl + img);
                    String href = element.select("a").attr("href");
                    String detail = baseUrl + href;
                    Element detailBody = getDocument(detail).body();
                    Elements bookMes = detailBody.getElementsByClass("bookdmore").select("p");
                    for (Element bookMe : bookMes) {
                        String label = bookMe.text();
                        handlerLabel(label, bookMessage);
                    }
                    Elements bookText = detailBody.getElementsByClass("bookdtext");
                    String introduction = bookText.select("p").get(0).text();
                    bookMessage.setIntroduction(introduction);

                    QueryWrapper<BookMessage> checkQueryWrapper = new QueryWrapper<>();
                    checkQueryWrapper.eq("name", name);
                    BookMessage check = bookMessageService.getOne(checkQueryWrapper);
                    if (Objects.isNull(check)) {
                        boolean save = bookMessageService.save(bookMessage);
                        if (!save) {
                            continue;
                        }
                    } else {
                        i++;
                        log.info(name + "===》已经存在！！！");
                        continue;
                    }
                    LambdaQueryWrapper<BookMessage> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.eq(BookMessage::getName, name);
                    queryWrapper.eq(BookMessage::getAuthor, bookMessage.getAuthor());
                    BookMessage bookMessageDO = bookMessageService.getOne(queryWrapper);

                    String attr = bookText.select("a").get(2).attr("href");
                    String chapterUrl = baseUrl + attr;
                    Element chapterBody = getDocument((chapterUrl)).body();
                    Elements a = chapterBody.getElementById("list").select("a");
                    for (Element one : a) {
                        saveChapter(baseUrl, bookMessageDO, one);
                    }
                    //向数据库插入消息，方便向用户推荐新书
                    saveMessage(bookMessage);
                    flag++;
                    log.info("======>抓取第{}本书{}完成===============", flag, name);
                    if (flag > 15) {
                        throw new RuntimeException("抓取两本书结束，线程退出");
                    }
                }
            } catch (Exception e) {
                log.info(e.getMessage());
                isRun = false;
            }
        }
        log.info("====抓取结束，线程退出====");
    }

    private void saveChapter(String baseUrl, BookMessage bookMessageDO, Element one) throws IOException {
        ChapterMessage chapterMessage = new ChapterMessage();
        String text = one.text();
        chapterMessage.setChapterName(text);
        chapterMessage.setBookId(bookMessageDO.getId());
        String chapUrl = baseUrl + one.attr("href");
        Element chapBody = getDocument(chapUrl).body();
        Element elementById = chapBody.getElementById("content");
        String content = elementById.child(1).text();
        chapterMessage.setChapterContext(content);

        QueryWrapper<ChapterMessage> messageDoQueryWrapper = new QueryWrapper<>();
        messageDoQueryWrapper.eq("chapter_name", text);
        ChapterMessage messageDO = chapterMessageService.getOne(messageDoQueryWrapper);
        if (Objects.nonNull(messageDO)) {
            return;
        }
        chapterMessageService.save(chapterMessage);
    }

    private void saveMessage(BookMessage bookMessage) {
        SystemNotice systemNotice = new SystemNotice();
        systemNotice.setFromId(-1L);
        systemNotice.setOperatorId(-9L);
        systemNotice.setOperatorName("爬虫");
        systemNotice.setContext("系统上新书了， 快来看看" + bookMessage.getName());
        systemNotice.setType(NoticeType.ALL.getCode());
        try {
            systemNoticeService.save(systemNotice);
            LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SysUser::getIsManager, IntBoolean.NO.getKey());
            List<SysUser> list = sysUserService.list(wrapper);
            list.forEach(user -> {
                NoticeUser noticeUser = new NoticeUser();
                noticeUser.setNoticeId(systemNotice.getId());
                noticeUser.setToId(user.getId());
                noticeUser.setOperatorId(-1L);
                noticeUser.setOperatorName("爬虫");
                noticeUserService.save(noticeUser);
            });
        } catch (Exception e) {
            log.error("爬虫插入信息时出现异常, 异常信息={}", e.getMessage());
        }
    }

    private Document getDocument(String baseUrl) throws IOException {
        Document index = Jsoup.parse(new URL(baseUrl), TIME_OUT);
        if (Objects.isNull(index)) {
            getDocument(baseUrl);
        }
        return index;
    }

    private void handlerLabel(String text, BookMessage bookMessage) {
        if (text.contains("分类")) {
            bookMessage.setKind(text.substring(3));
        }
        if (text.contains("类型")) {
            bookMessage.setType(text.substring(3));
        }
        if (text.contains("作者")) {
            bookMessage.setAuthor(text.substring(3));
        }
        if (text.contains("状态")) {
            bookMessage.setStatus(text.substring(3));
        }
        if (text.contains("大小")) {
            bookMessage.setSize(text.substring(3));
        }
        if (text.contains("最新章节")) {
            bookMessage.setLastChapter(text.substring(5));
        }
        if (text.contains("最新时间")) {
            String time = text.substring(5);
            bookMessage.setLastUpdateTime(DateUtil.parse(time));
        }
    }

    /**
     * 防止报错，定时任务注解优先级高于@resource
     *
     * @param applicationContext 上下文
     * @throws BeansException 拿不到bean
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }
}
